\subsection{Reprezentacja liczb}

Ludzie się przyzwyczaili do systemu dzisiętnego prawdopodobnie dlatego że każdy ma 10 palców.
Natomiast, liczba 10 nie odgrywa większej roli w nauce i matematyce.
Dwójkowy system liczbowy jest naturalny dla techniki cyfowej i elektroniki: 0 oznacza brak prądu, a 1 --- jego obecność.
10 w systemie dwójkowym to 2 w dziesiętnym; 100 w dwójkowym to 4 w dziesiętnym, itd.

Jeżeli w systemie liczbowym jest 10 znaków, jego \IT{podstawa} lub \IT{radix} to 10.
System dwójkowy ma \IT{podstawę} 2.

Ważne rzeczy, które warto sobie przypomnieć:
1) \IT{liczba} jest liczbą, natomiast \IT{cyfra} to umowny znak pisarski służący do zapisywania liczb;
2) sama w sobie liczba się nie zmienia przy przeliczaniu z jednego systemu na inny: zmienia się tylko sposób jej zapisu (lub reprezentacja w pamięci).

Jak skonwertować liczbę z jednego systemu na drugi?

Z notacji pozycyjnej korzysta się prawie wszędzie, to znaczy że każda cyfra posiada swoją wagę w zależności od jej usytuowania wewnątrz liczby.
Jeżeli 2 znajduje sie na ostatnim miejscu od prawej, jest to 2.
Jeżeli jest ona usytuowana w miejscu przed ostatnim, jest to 20.

Co znaczy $1234$?

$10^3 \cdot 1 + 10^2 \cdot 2 + 10^1 \cdot 3 + 1 \cdot 4$ = 1234 lub
$1000 \cdot 1 + 100 \cdot 2 + 10 \cdot 3 + 4 = 1234$

Tak samo to wygląda również w przypadku liczb binarnych, o tyle że podstawa tam to 2, a nie 10.
Co znaczy 0b101011?

$2^5 \cdot 1 + 2^4 \cdot 0 + 2^3 \cdot 1 + 2^2 \cdot 0 + 2^1 \cdot 1 + 2^0 \cdot 1 = 43$ lub
$32 \cdot 1 + 16 \cdot 0 + 8 \cdot 1 + 4 \cdot 0 + 2 \cdot 1 + 1 = 43$

Notację pozycyjną można przeciwstawić notacji niepozycjnej, np rzymskiej.
Prawdopodobnie przejście na notację pozycyjną zostało dokonane dlatego że w ten sposób na liczbach znacznie łatwiej jest wykonywać różnorodne operacje (mnożenie, dodawanie itd).

Rzeczywiście, liczby binarne można dodawać, odejmować itd dokładnie tak samo, jak się uczy w szkole, o tyle że są dostępne tylko dwie cyfry.

Liczby binarne są duże, kiedy ich się stosuje w kodach źródłowych i dump, także w tych przypadkach stosuje się systemu szesnastkowego. Cyfry 0-9 mają te same wartości co w systemie dziesiętnym, natomiast litery odpowiadają następującym wartościom: A = 10, B = 11, C = 12, D = 13, E = 14 oraz F = 15.

\begin{center}
\begin{longtable}{ | l | l | l | }
\hline
\HeaderColor szesnastkowy & \HeaderColor binarny & \HeaderColor dziesiętny \\
\hline
0	&0000	&0 \\
1	&0001	&1 \\
2	&0010	&2 \\
3	&0011	&3 \\
4	&0100	&4 \\
5	&0101	&5 \\
6	&0110	&6 \\
7	&0111	&7 \\
8	&1000	&8 \\
9	&1001	&9 \\
A	&1010	&10 \\
B	&1011	&11 \\
C	&1100	&12 \\
D	&1101	&13 \\
E	&1110	&14 \\
F	&1111	&15 \\
\hline
\end{longtable}
\end{center}

Jak zrozumieć z jakiego systemu się korzysta w konkretnym przypadku?

Liczby dziesiętne, z reguły, są zapisywane jak zwykle, czyli 1234. Ale niektóre asemblery pozwalają podkreślić to poprzez dostawienie prefiksu "d": 1234d.

Do liczb binarnych czasami się dodaje prefiks "0b": 0b100110111
(W \ac{GCC} jest dedykowane rozszerzenie
\footnote{\url{https://gcc.gnu.org/onlinedocs/gcc/Binary-constants.html}}).
Jest również jeszcze jeden sposób: sufiks "b", np: 100110111b.
W tej książce będę się trzymał konwencji prefiksowej "0b" dla liczb binarnych.

Liczby szestnaskowe mają prefiks "0x" w \CCpp i niektórych innych \ac{PL}: 0x1234ABCD.
Lub mają sufiks "h": 1234ABCDh --- zwykle są w ten sposób reprezentowane w asemblerach lub debuggerach.
Jeśli liczba zaczyna się od A..F, przed nimi się dostawia 0: 0ABCDEFh.
Za czasów 8-bitowych komputerów domowych, był również sposób zapisu liczb za pomocą prefiksu \$, np, \$ABCD.
W tej książce będę się trzymał prefiksu "0x" dla liczb szestnastkowych.

Czy trzeba umieć konwertować liczby w głowie? Tablicę liczb szestnastkowych składających się z jednej cyfry łatwo zapamiętać,
a zapamiętywać większe liczby raczej nie warto.

Przwdopodobnie najczęściej liczby szestnastkowe są spotykane w \ac{URL}-ach.
W ten sposób są kodowane litery nie z alfabetu łacińskiego.
Np:
\url{https://en.wiktionary.org/wiki/na\%C3\%AFvet\%C3\%A9} to \ac{URL} strona w Wiktionary o słowie \q{naïveté}.

\subsubsection{System Ósemkowy}

Jeszcze jeden system z którego się często korzystało w informatyce w przeszłości to 8 cyfr (0..7), każda
opisująca 3 bity, żeby można było łatwo skonwertować liczbę w obie strony.
Ten system prawie wszędzie został zamieniony na szesnastkowy, ale, o dziwo, w *NIX nadal jest program korzystający z systemu ósemkowego: \TT{chmod}.

\myindex{UNIX!chmod}
Jak wiedzą użytkownicy *NIX, argumentem \TT{chmod} jest liczba składająca się z 3 cyfr. Pierwsza cyfra określa uprawnienia właściciela pliku,
druga - to uprawnienia grupy (do której plik należy), trzecia dla reszty użytkowników.
Każda cyfra jest reprezentowana liczbą binarną:

\begin{center}
\begin{longtable}{ | l | l | l | }
\hline
\HeaderColor dziesiętny & \HeaderColor binarny & \HeaderColor wartość \\
\hline
7	&111	&\textbf{rwx} \\
6	&110	&\textbf{rw-} \\
5	&101	&\textbf{r-x} \\
4	&100	&\textbf{r-{}-} \\
3	&011	&\textbf{-wx} \\
2	&010	&\textbf{-w-} \\
1	&001	&\textbf{-{}-x} \\
0	&000	&\textbf{-{}-{}-} \\
\hline
\end{longtable}
\end{center}

Każdy bit jest dowiązany do flagi: read/write/execute.

Właśnie dlatego wsponiałem to o \TT{chmod}, cała liczba może być reprezentowana jako liczba ósemkowa.
Na przykład, weźmy 644.
Kiedy uruchamiasz \TT{chmod 644 file}, są wystawiane uprawnienia read/write dla właściciela, uprawnienia read dla grupy, i znowu,
read dla całej reszty.
Skonwertujmy liczbę 644 z systemu ósemkowego do binarnego, to będzie \TT{110100100}, lub (w grupach po 3 bity) \TT{110 100 100}.

Teraz widzimy, że każda 'trójka' opisuje uprawnienia dla właściciela/grupy/reszty: \TT{rw-}, druga to \TT{r--} i trzecia to \TT{r--}.

System ósemkowy był również popularny na starych komputerach typu PDP-8, dlatego że słowo tam mogło zawierać 12, 24 lub
36 bit, i wszystkie te liczby są podzielne przez 3, także wybór w tamtym środowisku systemu ósemkowego był całkiem logiczny.
Obecnie, wszystkie popularne komputery mają słowa/adresy 16, 32 lub 64 bitowe, i wszystkie te liczby są podzielne przez 4,
także system szestnastkowy jest teraz bardziej stosowny.

System ósemkowy jest supportowany przez wszystkie standardowe kompilatory \CCpp{}.
Czasami to jest źródłem nieporozumień, dlatego że liczby ósemkowe są kodowane z zerem z przodu, naprzykład, 0377 to 255.
I czasami, jak się zrobi pomyłkę i się napiszę "09" zamiast 9, to kompilator wyrzuci błąd.
GCC może wyrzucić coś w stylu:\\
\TT{error: invalid digit "9" in octal constant}.

% TBT

\subsubsection{Podzielność}

Kiedy się widzi liczbę 120, to można szybko się zorientować, że ta liczba jest podzielna przez 10, dlatego że ostatnią cyfrą jest 0.
Dokładnie tak samo, 123400 jest podzielne przez 100, bo ostatnie dwie liczby są zerami..

Dokładnie tak samo, liczba szestnastkowa 0x1230 jest podzielna przez 0x10 (lub 16), 0x123000 jest podzielne przez 0x1000 (lub 4096), itd.

Liczba binarna 0b1000101000 jest podzielna przez 0b1000 (8), itd.

Tę właściwość można wykorzystać, żeby szybko zrozumieć,
czy jakiś blok jest wyrównany według pewnej granicy.
Np, sekcje w \ac{PE}-plikach prawie zawsze zaczynają się od adresów kończących się 3 szestnastkowymi zerami:
0x41000, 0x10001000, itd.
Czyli prawie wszystkie sekcje w \ac{PE} są wyrównane według granicy 0x1000 (4096) bajt.

\subsubsection{Arytmetyka wielokrotnej precyzji}

\index{RSA}
Arytmetyka wielokrotnej precyzji (multi-precision arithmetic) może operować na dowolnie dużych liczbach,
które mogą być przechowywane w kilku bajtach.
Naprzykład, klucze RSA, mogą zajmować 4096 bit i nawet więcej.

W \InSqBrackets{\TAOCPvolII, 265} można znaleźć takie wytłumaczenie: kiedy się zapisuje liczbę wielokrotnej precyzji w kilku bajtach,
cała liczba może być reprezentowana jako zapisana w pewnym systemie liczbowym o podstawie $2^8=256$, i każda cyfra znajduje się w odpowiednim bajcie.
Dokłądnie tak samo, jak by się zapisywało liczbę wielokrotnej precyzji w kilku 32-bitowych całkowitoliczbowych wartościach,
każda cyfra idzie do osobnego 32-bitowego slotu, i można uważać tę liczbę za zapisaną w systemie o podstawie $2^{32}$.


\subsubsection{Liczby zmiennoprzecinkowe}

Żeby odróżniać liczby zmiennoprzecinkowe od całkowitoliczbowych, często, na końcu dodaje się ``.0'',
np $0.0$, $123.0$, itd.


